import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as CANNON from 'cannon-es'

const world = new CANNON.World()
world.gravity.set(0, -0.98, 0) // 设置重力

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight)
camera.position.set(0, 3, 5)
scene.add(camera)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.outputColorSpace = THREE.SRGBColorSpace

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

document.body.appendChild(renderer.domElement)

const axHelp = new THREE.AxesHelper(5)
scene.add(axHelp)

const cube = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshBasicMaterial({ color: 'yellowgreen' })
)
cube.position.set(0, 3, 0)
scene.add(cube)

const bodyMaterial = new CANNON.Material('boxMaterial')
// bodyMaterial.friction = 0
bodyMaterial.restitution = 1

const sphereBody = new CANNON.Body({
  mass: 1, position: new CANNON.Vec3(0, 3, 0),
  shape: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)),
  material: bodyMaterial
})
world.addBody(sphereBody)

const plane = new THREE.Mesh(
  new THREE.PlaneGeometry(10, 10),
  new THREE.MeshBasicMaterial({ color: 'grey' })
)
plane.rotation.x = -Math.PI / 2
scene.add(plane)

const planeMaterial = new CANNON.Material({ restitution: 1 })

const planeBody = new CANNON.Body({
  mass: 0,
  position: new CANNON.Vec3(0, 0, 0),
  material: planeMaterial
}).addShape(new CANNON.Plane())
planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)
world.addBody(planeBody)


const clock = new THREE.Clock()
let preTime = 0

const handleRender = () => {
  const nowTime = clock.getElapsedTime()
  const deltaTime = nowTime - preTime
  preTime = nowTime

  world.step(1 / 60, deltaTime, 3) // 补帧操作
  cube.position.copy(sphereBody.position as any)
  cube.quaternion.copy(sphereBody.quaternion as any)

  controls.update()
  renderer.render(scene, camera)
  window.requestAnimationFrame(handleRender)
}

const handleSize = () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
}

window.addEventListener('resize', handleSize)

handleRender()
